import { WriteStream, createWriteStream } from 'fs';
import { join } from 'path';

/** 写入流状态 */
export type StreamState = 'idle' | 'writing' | 'paused' | 'ended' | 'error';

/** 写入选项 */
export interface StreamWriterOptions {
  encoding?: BufferEncoding;
  highWaterMark?: number;
  autoClose?: boolean;
  flags?: string;
}

/** 写入状态统计 */
export interface StreamStats {
  bytesWritten: number;
  writes: number;
  queueMaxLength: number;
}

/** 写入器状态信息 */
export interface StreamStatus {
  state: StreamState;
  queueLength: number;
  pendingWrites: number;
  stats: StreamStats;
  error: Error | null;
}

/**
 * 安全的流式写入器，支持多次调用写入并自动处理背压
 */
export class StreamWriter {
  private filePath: string;
  private options: StreamWriterOptions;
  private stream: WriteStream | null = null;
  private state: StreamState = 'idle';
  private queue: Array<{
    data: string | Buffer;
    encoding: BufferEncoding;
    resolve: () => void;
    reject: (error: Error) => void;
  }> = [];
  private pendingWrites: number = 0;
  private error: Error | null = null;
  private stats: StreamStats = {
    bytesWritten: 0,
    writes: 0,
    queueMaxLength: 0
  };

  constructor(filePath: string, options: StreamWriterOptions = {}) {
    this.filePath = filePath;
    this.options = {
      encoding: 'utf8',
      highWaterMark: 16384,
      autoClose: true,
      ...options
    };
  }

  /** 获取当前状态 */
  public getStatus(): StreamStatus {
    return {
      state: this.state,
      queueLength: this.queue.length,
      pendingWrites: this.pendingWrites,
      stats: { ...this.stats },
      error: this.error
    };
  }

  /**
   * 写入数据
   * @param data 要写入的数据
   * @param encoding 编码方式，默认为 options 中设置的编码
   * @returns Promise，成功时解析，失败时拒绝
   */
  public async write(
    data: string | Buffer,
    encoding: BufferEncoding = this.options.encoding || 'utf8'
  ): Promise<void> {
    if (this.state === 'ended' || this.state === 'error') {
      return Promise.reject(
        new Error(`Cannot write in state ${this.state}`)
      );
    }

    this.initStream();

    // 增加统计
    this.stats.writes++;
    const dataSize = this.calculateDataSize(data, encoding);
    this.stats.bytesWritten += dataSize;

    // 如果队列过长则拒绝写入
    if (this.queue.length > 1000) {
      return Promise.reject(new Error('Write queue overflow'));
    }

    return new Promise((resolve, reject) => {
      // 如果流暂停或队列不为空，则加入队列
      if (this.state === 'paused' || this.queue.length > 0) {
        this.queue.push({ data, encoding, resolve, reject });
        this.stats.queueMaxLength = Math.max(
          this.stats.queueMaxLength,
          this.queue.length
        );
        if (this.state === 'idle') {
          this.state = 'writing';
          this.processQueue();
        }
        return;
      }

      // 直接写入
      this.pendingWrites++;
      const result = this.stream!.write(data, encoding, (err) => {
        this.pendingWrites--;
        if (err) {
          this.state = 'error';
          this.error = err;
          reject(err);
          this.clearQueue(err);
        } else {
          resolve();
        }
      });

      if (!result) {
        this.state = 'paused';
      }
    });
  }

  /**
   * 结束写入并关闭流
   * @returns Promise，成功时解析，失败时拒绝
   */
  public async end(): Promise<void> {
    if (this.state === 'ended' || this.state === 'error') {
      return;
    }

    // 等待队列处理完成
    while (this.queue.length > 0) {
      await new Promise((resolve) => setTimeout(resolve, 10));
    }

    // 等待所有待处理的写入完成
    while (this.pendingWrites > 0) {
      await new Promise((resolve) => setTimeout(resolve, 10));
    }

    return new Promise((resolve, reject) => {
      if (!this.stream) {
        return resolve();
      }

      this.state = 'ended';
      this.stream.end((err: any) => {
        if (err) {
          this.error = err;
          reject(err);
        } else {
          resolve();
        }
        if (this.options.autoClose) {
          this.stream = null;
        }
      });
    });
  }

  /** 销毁流，强制关闭并拒绝所有待处理的写入 */
  public destroy(): void {
    if (this.stream) {
      this.stream.destroy();
      this.stream = null;
    }
    this.state = 'ended';
    this.clearQueue(new Error('Stream destroyed'));
  }

  /** 初始化流 */
  private initStream(): void {
    if (this.stream) return;

    try {
      this.stream = createWriteStream(join(__dirname, this.filePath), {
        ...this.options,
        emitClose: true
      });

      this.state = 'idle';

      // 流事件处理
      this.stream.on('drain', () => {
        if (this.state === 'paused') {
          this.state = 'writing';
          this.processQueue();
        }
      });

      this.stream.on('error', (err: Error) => {
        console.error(`Stream error: ${err.message}`);
        this.error = err;
        this.state = 'error';
        this.clearQueue(err);
      });

      this.stream.on('close', () => {
        if (this.state !== 'ended') {
          console.warn('Stream closed unexpectedly');
          this.state = 'ended';
        }
      });

      this.stream.on('finish', () => {
        if (this.state === 'writing') {
          this.state = 'ended';
          if (this.options.autoClose) {
            this.stream = null;
          }
        }
      });
    } catch (err) {
      console.error(`Failed to create write stream: ${(err as Error).message}`);
      this.error = err as Error;
      this.state = 'error';
      throw err;
    }
  }

  /** 处理队列中的数据 */
  private processQueue(): void {
    while (this.queue.length > 0 && this.state === 'writing') {
      const item = this.queue.shift()!;
      this.pendingWrites++;

      // 修复：定义 result 变量
      const result = this.stream!.write(
        item.data,
        item.encoding,
        (err: Error | null | undefined) => {
          this.pendingWrites--;
          if (err) {
            this.state = 'error';
            this.error = err;
            item.reject(err);
            this.clearQueue(err);
          } else {
            item.resolve();
          }

          // 如果队列处理完且没有待处理的写入，则标记为空闲
          if (this.queue.length === 0 && this.pendingWrites === 0) {
            this.state = 'idle';
          }
        }
      );

      // 使用正确的变量名
      if (!result) {
        this.state = 'paused';
        break;
      }
    }
  }

  /** 清空队列并拒绝所有待处理的写入 */
  private clearQueue(err: Error): void {
    while (this.queue.length > 0) {
      this.queue.shift()!.reject(err);
    }
  }

  /** 计算数据大小 */
  private calculateDataSize(data: string | Buffer, encoding: BufferEncoding): number {
    if (typeof data === 'string') {
      return Buffer.from(data, encoding).length;
    } else {
      return data.length;
    }
  }
}

